package com.alks.function.service.impl.stockdept.pcfactorystockquery;

import com.alks.common.data.thread.UserIdThread;
import com.alks.common.utils.beanutils.BeanUtil;
import com.alks.entity.data.entity.PcSurplusDetail;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.SurpAccDetDto;
import com.alks.function.mapper.stockdept.pcfactorystockquery.SD_SQ_PcMtlAccMapper;
import com.alks.function.mapper.stockdept.pcfactorystockquery.SD_SQ_PcSurplusDetailMapper;
import com.alks.function.service.stockdept.pcfactorystockquery.ISurpAccService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.alks.entity.data.enums.ResultCodeEnum.INPUT_ERROR;

@Service
@Slf4j
@RequiredArgsConstructor
public class SurpAccServiceImpl extends ServiceImpl<SD_SQ_PcSurplusDetailMapper, PcSurplusDetail> implements ISurpAccService {
    private final SD_SQ_PcSurplusDetailMapper detailMapper;
    private final SD_SQ_PcMtlAccMapper accMapper;

    @Override
    public ResponseInfo getSurpAccHeadQuery(String slipNo, LocalDate slipDateStart, LocalDate slipDateEnd) {
        /*获取数据*/
        List<Map<String, Object>> dtos = lambdaQuery()
                .select(PcSurplusDetail::getSlipNo, PcSurplusDetail::getSlipDate, PcSurplusDetail::getSysUser)
                .like(slipNo != null && !slipNo.isEmpty(), PcSurplusDetail::getSlipNo, slipNo)
                .isNull(PcSurplusDetail::getCfmFlag)
                .eq(PcSurplusDetail::getSlipType, "I")
                .eq(PcSurplusDetail::getCompanyId,UserIdThread.get().getCompanyId())
                .ge(slipDateStart != null, PcSurplusDetail::getSlipDate, slipDateStart)
                .le(slipDateEnd != null, PcSurplusDetail::getSlipDate, slipDateEnd)
                .groupBy(PcSurplusDetail::getSlipNo).list().stream()
                .map(a -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("slipNo", a.getSlipNo());
                    /*转换输出格式*/
                    map.put("slipDate", a.getSlipDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    map.put("sysUser", a.getSysUser());
                    return map;
                }).collect(Collectors.toList());
        return ResponseInfo.ok(dtos);
    }

    @Override
    public ResponseInfo getSurpAccDetailQuery(String slipNo) {
        /*查询数据*/
        List<PcSurplusDetail> details = lambdaQuery()
                .eq(PcSurplusDetail::getSlipNo, slipNo)
                .eq(PcSurplusDetail::getSlipType, "I")
                .isNull(PcSurplusDetail::getCfmFlag).list();
        /*提取数据*/
        List<SurpAccDetDto> dtos = BeanUtil.copyList(details, SurpAccDetDto.class);
        return ResponseInfo.ok(dtos);
    }

    @Override
    public ResponseInfo getSurpAaccDetail(String slipNo, String mtlNo) {
        /*删除对应数据*/
        LambdaQueryWrapper<PcSurplusDetail> wrapper = new LambdaQueryWrapper<PcSurplusDetail>()
                .eq(PcSurplusDetail::getSlipNo, slipNo)
                .eq(PcSurplusDetail::getMtlNo, mtlNo);
        detailMapper.delete(wrapper);
        return ResponseInfo.ok();
    }

    @Override
    @Transactional
    public ResponseInfo getSurpAccUp(List<String> slipNo, Integer type) {
        String companyId = UserIdThread.get().getCompanyId();
        /*获取相关物料*/
        List<PcSurplusDetail> details = lambdaQuery()
                .select(PcSurplusDetail::getSlipNo,PcSurplusDetail::getMtlNo, PcSurplusDetail::getQty ,PcSurplusDetail::getCfmFlag)
                .eq(PcSurplusDetail::getCompanyId, companyId)
                .in(PcSurplusDetail::getSlipNo, slipNo)
                .eq(PcSurplusDetail::getSlipType, "I").list();
        /*判断数据是否正确*/
        if (type.equals(1)){
            for (PcSurplusDetail detail : details) {
                if (detail.equals("Y")){
                    log.warn("异常接口：getSurpAccUp\n异常原因：尝试确认已确认单据，单据号：{}",detail.getSlipNo());
                    return ResponseInfo.error("存在已确认入库单据", INPUT_ERROR.getCode());
                }
            }
        }else if (type.equals(2)){
            for (PcSurplusDetail detail : details) {
                if (detail.equals("Y")){
                    log.warn("异常接口：getSurpAccUp\n异常原因：尝试取消未确认单据，单据号：{}",detail.getSlipNo());
                    return ResponseInfo.error("存在未确认入库单据", INPUT_ERROR.getCode());
                }
            }
        }
        Map<String, BigDecimal> mtlQtys = details.stream().collect(Collectors.toMap(PcSurplusDetail::getMtlNo, a -> a.getQty()));
        List<String> mtlNos = details.stream().map(PcSurplusDetail::getMtlNo).collect(Collectors.toList());
        /*更新数据*/
        lambdaUpdate()
                .in(PcSurplusDetail::getSlipNo, slipNo)
                .eq(PcSurplusDetail::getCompanyId, companyId)
                .eq(PcSurplusDetail::getSlipType, "I")
                .set(type == 1, PcSurplusDetail::getCfmFlag, "Y")
                .set(type == 1,PcSurplusDetail::getCfmDate, LocalDateTime.now())
                .set(type == 1,PcSurplusDetail::getCfmUser, UserIdThread.get().getUserName())
                .set(type == 2, PcSurplusDetail::getCfmFlag, null)
                .set(type == 2, PcSurplusDetail::getCfmDate, null)
                .set(type == 2, PcSurplusDetail::getCfmUser, null)
                .update();
        /*更新仓库库存*/
        if (type.equals(1)) {
            accMapper.stkOutByMap(mtlQtys, companyId);
            accMapper.traDateUp(mtlNos,LocalDate.now().atStartOfDay() , companyId);
        } else if (type.equals(2)) {
            accMapper.stkReduceByMap(mtlQtys, companyId);
            accMapper.traDateUp(mtlNos, LocalDate.now().atStartOfDay(), companyId);
        }
        return ResponseInfo.ok();
    }
}
